﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;

#if UNITY_EDITOR
using UnityEditor;
#endif

namespace QFramework
{
    [CreateAssetMenu(menuName = "@ItemKit/Create Item Database")]
    public class ItemDatabase : ScriptableObject
    {
        [DisplayLabel("命名空间：")]
        public string Namespace = "QFramework.Example";
        public List<Item> Items;
    }
    
#if UNITY_EDITOR
    
    [UnityEditor.CustomEditor(typeof(ItemDatabase))]
    public class ItemDatabaseEditor : UnityEditor.Editor
    {
        private SerializedProperty mItems;

        public class ItemEditorObj
        {
            public bool Foldout = false;

            public Editor Editor = null;

            public Item Item = null;
        }

        private List<ItemEditorObj> mItemEditors = new List<ItemEditorObj>();

        private void OnEnable()
        {
            mItems = serializedObject.FindProperty("Items");
            RefreshItemEditors();
        }

        /// <summary>
        /// 刷新编辑器
        /// </summary>
        void RefreshItemEditors()
        {
            mItemEditors.Clear();

            for (int i = 0; i < mItems.arraySize; i++)
            {
                var itemSo = mItems.GetArrayElementAtIndex(i);
                var editor = CreateEditor(itemSo.objectReferenceValue);
                mItemEditors.Add(new ItemEditorObj()
                {
                    Editor = editor,
                    Item = itemSo.objectReferenceValue as Item
                });
            }
        }

        private string mSearchKey = "";
        FluentGUIStyle mHeader = FluentGUIStyle.Label().FontBold();
        private Queue<Action> mActionQueue = new Queue<Action>();
            
        public override void OnInspectorGUI()
        {
            serializedObject.Update();
            
            GUILayout.BeginVertical("box");
            // 忽略 Items 的绘制
            serializedObject.DrawProperties(false, 0, "Items");

            if (mItemEditors.Count != mItems.arraySize)
            {
                RefreshItemEditors();
            }

            if (GUILayout.Button("生成代码"))
            {
                var itemDB = target as ItemDatabase;

                string filePath = AssetDatabase.GetAssetPath(target).GetFolderPath() + "/items.cs";

                // 创建代码
                var rootCode = new RootCode()
                    .Using("QFramework")
                    .Using("UnityEngine")
                    .EmptyLine()
                    .Namespace(itemDB.Namespace, ns =>
                    {
                        ns.Class("Items", String.Empty, false, false, c =>
                        {
                            foreach (var itemConfig in itemDB.Items)
                            {
                                string line = $"public static string {itemConfig.Key} = \"{itemConfig.Key}\";";
                                Debug.Log(line);
                                c.Custom(line);
                            }
                        });
                    });

                using var fileWriter = File.CreateText(filePath);
                var codeWriter = new FileCodeWriter(fileWriter);
                rootCode.Gen(codeWriter);
            
                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();
            }
            GUILayout.EndVertical();
            
            EditorGUILayout.Separator(); // 分隔符
            GUILayout.Label("物品列表：", mHeader);
            // 搜索
            GUILayout.BeginHorizontal();
            GUILayout.Label("搜索：", GUILayout.Width(40));
            mSearchKey = EditorGUILayout.TextField(mSearchKey);
            GUILayout.EndHorizontal();

            // 遍历
            for (int i = 0; i < mItemEditors.Count; i++)
            {
                var itemEditor = mItemEditors[i];

                if (!itemEditor.Item.Name.Contains(mSearchKey) && !itemEditor.Item.Key.Contains(mSearchKey))
                {
                    continue;
                }
                
                GUILayout.BeginVertical("box");
                {
                    GUILayout.BeginHorizontal();
                    itemEditor.Foldout = EditorGUILayout.Foldout(itemEditor.Foldout, itemEditor.Item.GetName);
                    
                    GUILayout.FlexibleSpace();
                    if (GUILayout.Button("-"))
                    {
                        var index = i;
                        if (EditorUtility.DisplayDialog("删除物品", "确定要删除吗？", "删除", "取消"))
                        {
                            mActionQueue.Enqueue(() =>
                            {
                                var arrayElement = mItems.GetArrayElementAtIndex(index);
                                AssetDatabase.RemoveObjectFromAsset(arrayElement.objectReferenceValue);
                                mItems.DeleteArrayElementAtIndex(index);
                                serializedObject.ApplyModifiedPropertiesWithoutUndo();
                                AssetDatabase.SaveAssets();
                                AssetDatabase.Refresh();
                            });
                        }
                    }
                    GUILayout.EndHorizontal();

                    if (itemEditor.Foldout)
                    {
                        itemEditor.Editor.OnInspectorGUI();
                    }
                }
                GUILayout.EndVertical();
            }
            
            // 添加物品
            if (GUILayout.Button("创建物品"))
            {
                mActionQueue.Enqueue(() =>
                {
                    var itemConfig = CreateInstance<Item>();
                    itemConfig.name = nameof(Item);
                    itemConfig.Name = "新物品";
                    itemConfig.Key = "item_key";
                    
                    AssetDatabase.AddObjectToAsset(itemConfig, target);
                    mItems.InsertArrayElementAtIndex(mItems.arraySize);
                    
                    var arrayElement = mItems.GetArrayElementAtIndex(mItems.arraySize - 1);
                    arrayElement.objectReferenceValue = itemConfig;
                    serializedObject.ApplyModifiedPropertiesWithoutUndo();
                
                    AssetDatabase.SaveAssets();
                    AssetDatabase.Refresh();
                });
            }

            if (mActionQueue.Count > 0)
            {
                mActionQueue.Dequeue().Invoke();
            }
            serializedObject.ApplyModifiedProperties();
        }
    }
#endif
}